
define(['ionic', 'services'], function () {
    angular.module('U9Mobile.services')
        .factory('ContactService', ['$q', '$filter', '$cordovaContacts', 'ConnectService', 'AppManager', 'OperaterUtil', 'DuDuUtil', 'UserService', 'UtilService', 'AppConstants',
            function ($q, $filter, $cordovaContacts, ConnectService, AppManager, OperaterUtil, DuDuUtil, UserService, UtilService, AppConstants) {
                var o = {},
                    getContactFns  = {},
                    contactsCache = {},
                    sealCache = {};

                getContactFns.default = function () {
                    return [];
                };

                o.bindGetContactFn = function (appId, fn) {
                    getContactFns[appId] = fn;
                };
                o.getInitParticipators = function () {
                    var defer = $q.defer();

                    var activeAppId = AppManager.getActiveAppId();
                    if (!activeAppId || !getContactFns[activeAppId]) {
                        activeAppId = 'default';
                    }
                    $q.when(getContactFns[activeAppId]()).then(function(contacts) {
                        defer.resolve(contacts);
                    }, function () {
                        defer.reject();
                    });

                    return defer.promise;
                };

                o.createConference = function (phones) {
                    var defer = $q.defer();
                    
                    var user = UserService.getUserDetailInfo();
                    if (!user || !user.tel) {
                        defer.reject('发起人不存在可用的号码');
                    } else {
                        DuDuUtil.createConference(user.id, user.tel, phones).then(function () {
                            defer.resolve();
                        }, function () {
                            defer.reject('发起通话失败');
                        });
                    }

                    return defer.promise;
                };
                o.queryContacts = function (source) {
                    var defer = $q.defer();

                    var cache = source ? contactsCache.departmentContacts : contactsCache.phoneContacts,
                        queryFn = source ? queryDepartmentContacts : queryPhoneContacts;
                    $q.when(
                        cache ? cache : queryFn()
                    ).then(function(contacts) {
                        angular.forEach(contacts, function (contact) {
                            contact.checked = false;
                        });
                        defer.resolve(contacts);
                    }, function () {
                        defer.reject();
                    });

                    return defer.promise;
                };
                o.getContacts = function (char, source) {
                    var contacts = source ? contactsCache.departmentContacts : contactsCache.phoneContacts;
                    var results = $filter('filter')(contacts, function (contact) {
                        if (contact.firstchar.indexOf(char) === 0) {
                            return true;
                        }
                    });
                    angular.forEach(results, function (result) {
                        result.checked = false;
                    });
                    return results;
                };
                o.filterContacts = function (filter, source) {
                    var defer = $q.defer();

                    if (source) {
                        searchOperaters(filter, false).then(function (results) {
                            defer.resolve(results);
                        }, function () {
                            defer.resolve([]);
                        });
                    } else {
                        var results = $filter('filter')(contactsCache.phoneContacts, function (contact) {
                            if (contact.name.indexOf(filter) !== -1 ||
                                (contact.phone && contact.phone.indexOf(filter) !== -1)
                            ) {
                                return true;
                            }
                        });
                        angular.forEach(results, function (result) {
                            result.checked = false;
                        });
                        defer.resolve(results);
                    }

                    return defer.promise;
                };

                return o;

                function queryDepartmentContacts () {
                    var defer = $q.defer();

                    UtilService.showLoading();
                    OperaterUtil.queryDepOperater(UserService.getUserParams('account')).then(function (results) {
                        var formatResults = formatDepartmentContacts(results);
                        contactsCache.departmentContacts = formatResults;
                        defer.resolve(angular.copy(formatResults));
                    }, function () {
                        defer.reject();
                    }).finally(function () {
                        UtilService.hideLoading();
                    });

                    return defer.promise;
                }
                function searchOperaters (keyword, isQueryFriend) {
                    var defer = $q.defer();

                    var userId = UserService.getUserDetailInfo().id;
                    if (userId) {
                        OperaterUtil.queryOperaters(keyword, isQueryFriend, userId).then(function (operaters) {
                            var contacts = [];
                            angular.forEach(operaters, function (user) {
                                if (!sealCache.hasOwnProperty(user.OperaterID) && user.Seal) {
                                    sealCache[user.OperaterID] = 'data:image/png;base64,' + user.Seal;
                                }
                                contacts.push({
                                    name: user.OperaterName,
                                    phone: user.Phone || '',
                                    photo: sealCache[user.OperaterID]
                                });
                            });
                            defer.resolve(contacts);
                        }, function () {
                            defer.reject();
                        });
                    } else {
                        defer.reject([]);
                    }

                    return defer.promise;
                }
                function queryPhoneContacts () {
                    var defer = $q.defer();

                    if (!navigator.contacts) {
                        defer.reject();
                    } else {
                        UtilService.showLoading();
                        var options = new ContactFindOptions();
                        options.filter = "";
                        options.multiple = true;
                        options.fields = ["displayName", "phoneNumbers"];
                        $cordovaContacts.find(options).then(function (results) {
                            var formatResults = formatPhoneContacts(results);
                            contactsCache.phoneContacts = formatResults;
                            defer.resolve(formatResults);
                            UtilService.hideLoading();
                        }, function () {
                            defer.reject();
                            UtilService.hideLoading();
                        });
                    }

                    return defer.promise;
                }
                function formatDepartmentContacts (users) {
                    var contacts = [];
                    angular.forEach(users, function (user) {
                        var camelChars = pinyin.getCamelChars(user.OperaterName);
                        if (camelChars.length > 0) {
                            var camelChar = camelChars[0].toUpperCase();
                            if (!sealCache.hasOwnProperty(user.OperaterID) && user.Seal) {
                                sealCache[user.OperaterID] = 'data:image/png;base64,' + user.Seal;
                            }
                            contacts.push({
                                name: user.OperaterName,
                                phone: user.Tel || '',
                                photo: sealCache[user.OperaterID],
                                firstchar: camelChar
                            });
                        }
                    });
                    return $filter('orderBy')(contacts, 'firstchar', false);
                }
                function formatPhoneContacts (contacts) {
                    var result = [],
                        t;
                    angular.forEach(contacts, function (contact) {
                        if (contact.name && angular.isArray(contact.phoneNumbers)) {
                            t = {
                                name: (contact.name.familyName ? contact.name.familyName : '') + (contact.name.givenName ? contact.name.givenName : ''),
                                phone: getPhoneNum(contact.phoneNumbers),
                                photo: null//contact.photos ? result.photos[0].value : null
                            };
                            var camelChars = pinyin.getCamelChars(t.name);
                            if (camelChars.length > 0) {
                                t.firstchar = camelChars[0].toUpperCase();
                                result.push(t);
                            }
                        }
                    });
                    return $filter('orderBy')(result, 'firstchar', false);
                }
                function getPhoneNum (phoneNums) {
                    var len = phoneNums.length,
                        phone = '';
                    for (var i = 0; i < len; i++) {
                        if (phoneNums[i].value !== '' && phoneNums[i].value !== undefined) {
                            phone = phoneNums[i].value.replace(/-/g, '');
                            break;
                        }
                    }
                    return phone;
                }
            }
        ]);
});